﻿using CommonClass;
using EncryptProject;
using SurveillanceLib;
using SurveillancePro.Base.Common;
using SurveillancePro.Base.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;

namespace DeviceMgtModule.Models
{
    /// <summary>
    /// 设备属性
    /// </summary>
    public class DeviceModel : ViewModelBase, IDataErrorInfo, IEquatable<DeviceModel>
    {
        #region Const Fields

        private const int MAXLENGTH_DRIVERTEXT = 40;

        #endregion

        #region Private Fields

        private static DataSet _dsTreeNode;
        private static SurveillanceDAL _dataOperation = new SurveillanceDAL();
        private DataRow _row;
        
        #endregion

        #region Constructor

        /// <summary>
        /// 只需要表结构的数据集
        /// </summary>
        /// <param name="dsTreeNode"></param>
        public DeviceModel()
        {
            if (_dsTreeNode == null ||
                _dsTreeNode.Tables.Count <= 0)
                throw new Exception("数据库异常！");

            _row = _dsTreeNode.Tables[0].NewRow(); // 添加一个新数据行
            _fillDriverTypesList(); // 加载 DriverTypes 下拉框
            Status = "1"; // 启用设备
        }

        /// <summary>
        /// 选中的指定行
        /// </summary>
        /// <param name="row"></param>
        public DeviceModel(DataRow row)
        {
            this._row = row;
            _fillDriverTypesList(); // 加载 DriverTypes 下拉框
        }

        #endregion

        #region IEquatable Members

        public bool Equals(DeviceModel obj)
        {
            return this._row["ID"].ToString() == obj._row["ID"].ToString();
        }

        #endregion

        #region Public Properties

        #region 用于验证的附加属性

        /// <summary>
        /// 保留修改前的 DeviceText——验证重复
        /// </summary>
        public string OrigDriverText { private get; set; }

        /// <summary>
        /// 保留修改前的 DeviceIP——验证重复
        /// </summary>
        public string OrigDriverIP { private get; set; }

        /// <summary>
        /// 保留修改前的 DevicePort——验证重复
        /// </summary>
        public string OrigDriverPort { private get; set; }

        /// <summary>
        /// 获取 DeviceList 列表，用于判断 DriverText 是否重复
        /// </summary>
        public System.Collections.ObjectModel.ObservableCollection<DeviceModel> DeviceList { private get; set; }

        #endregion

        #region 与界面绑定的属性

        /// <summary>
        /// DriverTypes
        /// </summary>
        public List<ArgModel> DriverTypes { get; private set; }

        private string _driverPwd;
        /// <summary>
        /// 密码
        /// </summary>
        public string DriverPwd
        {
            get { return _driverPwd; }
            set
            {
                if (_driverPwd == value) return;
                _driverPwd = value;
                base.OnPropertyChanged("DriverPwd");
            }
        }

        private string _driverConfirmPwd;
        /// <summary>
        /// 确认密码
        /// </summary>
        public string DriverConfirmPwd
        {
            get { return _driverConfirmPwd; }
            set
            {
                if (_driverConfirmPwd == value) return;
                _driverConfirmPwd = value;
                base.OnPropertyChanged("DriverConfirmPwd");
            }
        }

        private bool _isSelected;
        /// <summary>
        /// 是否选择
        /// </summary>
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value == _isSelected) return;
                _isSelected = value;
                base.OnPropertyChanged("IsSelected");
            }
        }

        #endregion

        /// <summary>
        /// ID
        /// </summary>
        [System.ComponentModel.DataAnnotations.Key]
        public string ID
        {
            get { return _row["ID"].ToString(); }
            set
            {
                if (value == _row["ID"].ToString()) return;
                _row["ID"] = value;
                base.OnPropertyChanged("ID");
            }
        }

        /// <summary>
        /// ParentID
        /// </summary>
        public string ParentID
        {
            get { return _row["ParentID"].ToString(); }
            set
            {
                if (value == _row["ParentID"].ToString()) return;
                _row["ParentID"] = value;
                base.OnPropertyChanged("ParentID");
            }
        }

        /// <summary>
        /// DriverIP
        /// </summary>
        public string DriverIP
        {
            get { return _row["TreeName"].ToString(); }
            set
            {
                if (value == _row["TreeName"].ToString()) return;
                _row["TreeName"] = value;
                base.OnPropertyChanged("DriverIP");
            }
        }

        /// <summary>
        /// DriverText
        /// </summary>
        public string DriverText
        {
            get { return _row["TreeText"].ToString(); }
            set
            {
                if (value == _row["TreeText"].ToString()) return;
                _row["TreeText"] = value;
                base.OnPropertyChanged("DriverText");
            }
        }

        /// <summary>
        /// DriverName
        /// </summary>
        public string DriverName
        {
            get { return _row["DriverName"].ToString(); }
            set
            {
                if (value == _row["DriverName"].ToString()) return;
                _row["DriverName"] = value;
                base.OnPropertyChanged("DriverName");
            }
        }

        /// <summary>
        /// DriverPwd
        /// </summary>
        public string DriverPassword
        {
            get { return _row["DriverPwd"].ToString(); }
        }

        /// <summary>
        /// DriverPort
        /// </summary>
        public string DriverPort
        {
            get { return _row["DriverPort"].ToString(); }
            set
            {
                if (value == _row["DriverPort"].ToString()) return;
                _row["DriverPort"] = value;
                base.OnPropertyChanged("DriverPort");
            }
        }

        /// <summary>
        /// ExceptChannel
        /// </summary>
        public string ExceptChannel
        {
            get { return _row["ExceptChannel"].ToString(); }
            set
            {
                if (value == _row["ExceptChannel"].ToString()) return;
                _row["ExceptChannel"] = value;
                base.OnPropertyChanged("ExceptChannel");
            }
        }

        /// <summary>
        /// Status
        /// </summary>
        public string Status
        {
            get { return _row["Status"].ToString(); }
            set
            {
                if (value == _row["Status"].ToString()) return;
                _row["Status"] = value;
                base.OnPropertyChanged("Status");
            }
        }

        /// <summary>
        /// DriverType
        /// </summary>
        public string DriverType
        {
            get { return _row["DriverType"].ToString(); }
            set
            {
                if (value == _row["DriverType"].ToString()) return;
                _row["DriverType"] = value;
                base.OnPropertyChanged("DriverType");
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// 填充设备类型下拉值
        /// </summary>
        private void _fillDriverTypesList()
        {
            ArgModel argType;
            DriverTypes = new List<ArgModel>();

            // 填充 DriverTypeEnum 枚举
            foreach (DriverTypeEnum driverType in Utilities.GetEnumValues<DriverTypeEnum>())
            {
                argType = new ArgModel()
                {
                    sKey = driverType.ToString(),
                    sValue = Utilities.GetEnumDisplayDescription(driverType),
                };
                DriverTypes.Add(argType);
            }

            if (string.IsNullOrWhiteSpace(DriverType) &&
                DriverTypes.Count > 0)
                DriverType = DriverTypes.FirstOrDefault().sKey; // 对下拉赋初值
        }

        /// <summary>
        /// 特殊数据处理
        /// </summary>
        /// <param name="outStatus"></param>
        private void _setSpecifiedValue(out int outStatus)
        {
            if (!int.TryParse(Status, out outStatus)) // 解析设备状态
            {
                outStatus = 0;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// 创建
        /// </summary>
        /// <returns></returns>
        public int SaveNew()
        {
            int outStatus;
            _setSpecifiedValue(out outStatus);

            return _dataOperation.AddTreeNodeItem(DriverText.Trim(),
                DriverIP.Trim(), DriverName.Trim(),
                EncryptAlgorithmHelper.Encrypt2(DriverPwd.Trim(), Utilities.MachineCode),
                DriverPort.Trim(), ExceptChannel.Trim(),
                outStatus, DriverType.ToString());
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <returns></returns>
        public int SaveModified()
        {
            int outStatus;
            _setSpecifiedValue(out outStatus);

            return _dataOperation.EditTreeNodeItem(ID.Trim(),
                DriverText.Trim(), DriverIP.Trim(), DriverName.Trim(),
                EncryptAlgorithmHelper.Encrypt2(DriverPwd.Trim(), Utilities.MachineCode),
                DriverPort.Trim(), ExceptChannel.Trim(),
                outStatus, DriverType.ToString());
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="deleteID">删除 ID</param>
        /// <returns></returns>
        public int DeleteRec(string deleteID)
        {
            if (string.IsNullOrWhiteSpace(deleteID))
                return -1;
            else
                return _dataOperation.DeleteTreeNodeItem(deleteID);
        }


        /// <summary>
        /// 加载全部【Static 方法】
        /// </summary>
        /// <returns></returns>
        public static DataRowCollection Load_All()
        {
            if (_dataOperation == null)
                return null;

            _dsTreeNode = _dataOperation.GetDataSet(SurveillanceDAL.QUERY_GET_ALLTREENODEDATA,
                null, "db_VWMSConnectionString", string.Format("{0}.exe", System.Windows.Forms.Application.ProductName));

            if (_dsTreeNode != null && _dsTreeNode.Tables.Count > 0)
                return _dsTreeNode.Tables[0].Rows;
            else
                return null;
        }

        #endregion

        #region IDataErrorInfo Members

        string IDataErrorInfo.Error
        {
            get
            {
                return null;
            }
        }

        string IDataErrorInfo.this[string propertyName]
        {
            get
            {
                return this._getValidationError(propertyName);
            }
        }

        #endregion

        #region Validation -- 默认验证全部值

        /// <summary>
        /// Last Error Information
        /// </summary>
        public string ErrorInfo { get; private set; }

        /// <summary>
        /// Returns true if this object has no validation errors.
        /// </summary>
        public int IsValid
        {
            get
            {
                int errorCount = 0;
                string errorInfo;

                foreach (string property in validatedProperties)
                { 
                    errorInfo = _getValidationError(property);
                    if (!string.IsNullOrWhiteSpace(errorInfo))
                    {
                        ErrorInfo = errorInfo; // 记录最后一个错误信息
                        errorCount += 1; // 记录错误个数
                    }
                }

                return errorCount;
            }
        }

        static readonly string[] validatedProperties = 
        {
            "DriverIP",
            "DriverPort",
            "DriverText",
            "DriverName",
            "DriverPwd",
            "DriverConfirmPwd",
        };

        string _getValidationError(string propertyName)
        {
            if (Array.IndexOf(validatedProperties, propertyName) < 0)
                return null;

            string error = null; // 初值

            switch (propertyName)
            {
                case "DriverIP":
                    error = this._validateDriverIP();
                    break;
                case "DriverPort":
                    error = this._validateDriverPort();
                    break;
                case "DriverText":
                    error = this._validateDriverText();
                    break;
                case "DriverName":
                    error = this._validateDriverName();
                    break;
                case "DriverPwd":
                    error = this._validateDriverPwd();
                    break;
                case "DriverConfirmPwd":
                    error = this._validateDriverConfirmPwd();
                    break;



                default:
#if DEBUG
                    Debug.WriteLine(string.Format("异常：{0}", propertyName));
#endif
                    break;
            }

            return error;
        }

        string _validateDriverIP()
        {
            if (ErrorValidationUtil.IsStringMissing(this.DriverIP))
                return "缺少设备 IP";
            else if (!Utilities.ValidIP(this.DriverIP))
                return "设备 IP 不合法";

            return null;
        }

        string _validateDriverPort()
        {
            if (ErrorValidationUtil.IsStringMissing(this.DriverPort))
                return "缺少设备端口号";
            else if (!Utilities.ValidIPPort(this.DriverPort))
                return "设备端口号不合法";
            else if (!_checkDriver(this.OrigDriverIP, this.OrigDriverPort,
                this.DriverIP, this.DriverPort)) // 判断是否存在相同的设备 IP 与端口号
                return "已存在相同的设备 IP 与端口号";

            return null;
        }

        string _validateDriverName()
        {
            if (ErrorValidationUtil.IsStringMissing(this.DriverName))
                return "缺少设备登录用户名";

            return null;
        }

        string _validateDriverPwd()
        {
            if (ErrorValidationUtil.IsStringMissing(this.DriverPwd))
                return "缺少设备登录密码";
            //else if (string.IsNullOrWhiteSpace(this.DriverConfirmPwd) ||
            //    !this.DriverPwd.Equals(this.DriverConfirmPwd))
            //    return "两次输入的密码不一致";

            return null;
        }

        string _validateDriverConfirmPwd()
        {
            if (ErrorValidationUtil.IsStringMissing(this.DriverConfirmPwd))
                return "缺少设备登录确认密码";
            else if (string.IsNullOrWhiteSpace(this.DriverPwd) ||
                !this.DriverConfirmPwd.Equals(this.DriverPwd))
                return "两次输入的密码不一致";

            return null;
        }

        string _validateDriverText()
        {
            int maxlength = MAXLENGTH_DRIVERTEXT;

            if (ErrorValidationUtil.IsStringMissing(this.DriverText))
                return "缺少设备名称";
            else if (this.DriverText.Length > maxlength)
                return string.Format("设备名称长度必须在{0}个字符以内", maxlength);
            else if (!_checkDriverText(this.OrigDriverText, this.DriverText)) // 判断是否存在相同的 DriverText
                return "设备名称已存在";

            return null;
        }



        /// <summary>
        /// 验证设备 IP 与端口号是否已同时存在
        /// </summary>
        /// <param name="origDriverIP">原 DriverIP，新建时可直接传空</param>
        /// <param name="origDriverPort">原 DriverPort，新建时可直接传空</param>
        /// <param name="driverIP">现 DriverIP</param>
        /// <param name="driverPort">现 DriverPort</param>
        /// <returns>True: 可以更新; False：不能更新</returns>
        private bool _checkDriver(string origDriverIP, string origDriverPort,
            string driverIP, string driverPort)
        {
            if (!string.IsNullOrWhiteSpace(origDriverIP) &&
                !string.IsNullOrWhiteSpace(origDriverPort) &&
                origDriverIP.Equals(this.DriverIP) &&
                origDriverPort.Equals(this.DriverPort)) // 修改情况时，并且没有修改 DriverIP 与 DriverPort
            {
                return true;
            }

            // 新建情况 | 修改了 DriverIP 与 DriverPort 时
            DeviceModel model = null;

            try
            {
                if (DeviceList != null)
                {
                    foreach (DeviceModel device in DeviceList)
                    {
                        if (device.DriverIP.Equals(driverIP) &&
                            device.DriverPort.Equals(driverPort))
                        {
                            model = device;
                            break;
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }

            return model == null;
        }

        /// <summary>
        /// 验证 DriverText 是否已存在
        /// </summary>
        /// <param name="origDriverText">原 DriverText，新建时可直接传空</param>
        /// <param name="driverText">现 DriverText</param>
        /// <returns>True: 可以更新; False：不能更新</returns>
        private bool _checkDriverText(string origDriverText, string driverText)
        {
            if (!string.IsNullOrWhiteSpace(origDriverText) && 
                origDriverText.Equals(this.DriverText)) // 修改情况时，并且没有修改 DriverText
            {
                return true;
            }

            // 新建情况 | 修改了 DriverText 时
            DeviceModel model = null;

            try
            {
                if (DeviceList != null)
                {
                    foreach (DeviceModel device in DeviceList)
                    {
                        if (device.DriverText.Equals(driverText))
                        {
                            model = device;
                            break;
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }

            return model == null;
        }

        #endregion // Validation
    }
}
